import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get.dart';
import 'package:laos_mall/common/style/extension_util.dart';
import 'app_empty.dart';
import 'app_refresh.dart';
import 'base_controller.dart';

class PageSizeLogic<T> extends BaseController {
  List<T> dataSource = [];
  bool noMore = false;
  bool isRefresh = false;
  bool autoPage = true;
  var params = ListParameter.defaultArg();
  Future<List<T>?> Function()? future;

  void onRefresh() {
    noMore = false;
    isRefresh = true;
    params.pageNum = 1;
    requestData();
  }

  Future<void> requestData() async {
    if(future == null) return;
    var response = await future!();
    var dataList = response;
    if (isRefresh) {
      dataSource.clear();
    }
    dataSource.addAll(dataList ?? []);
    if ((dataList?.length ?? 0) < params.pageSize) {

        noMore = true;

    } else {
      if(!autoPage){
       noMore = true;
      }else {
        noMore = false;
      }
    }

    update();
  }

  void refreshCurrent(){
    update();
  }

  void onLoadMore() {
    isRefresh = false;
    params.pageNum ++;
    requestData();
  }

  @override
  void onInit() {
    request = requestData;
    super.onInit();
  }
}

typedef ItemWidgetBuilder<T> = Widget Function(BuildContext context, int index, T data);
class PageSizeView<T> extends GetView<PageSizeLogic<T>>{
  @override
  final  PageSizeLogic<T> controller;
   PageSizeView({super.key, required this.itemBuilder,required this.controller,this.shrinkWrap = true,this.separatorBuilder,this.itemCount,this.childBuilder,this.physics,this.emptyView});
  final ItemWidgetBuilder<T> itemBuilder;
  final IndexedWidgetBuilder? separatorBuilder;
  final bool shrinkWrap;
  ///用于测试 不建议写
  final int? itemCount;
  final Widget Function(BuildContext context, int index)? childBuilder;
  ScrollPhysics? physics;
  final Widget? emptyView;
  @override
  Widget build(BuildContext context) {
    return
    AppRefresh(
        onRefresh: () {
          controller.onRefresh();
        },
        child:
        controller.dataSource.isEmpty
            ?  emptyView ?? AppEmptyView():
        ListView.separated(padding: EdgeInsets.zero,itemBuilder: (context, index) {
          if (index == controller.dataSource.length) {
            controller.onLoadMore();
            return Visibility(visible: !controller.noMore, child: const CupertinoActivityIndicator());
          }
          return itemBuilder(context, index, controller.dataSource[index]);
        },physics:physics ,shrinkWrap: shrinkWrap,separatorBuilder: separatorBuilder ?? (context,index)=>Container(), itemCount: controller.noMore ? (itemCount ?? controller.dataSource.length) : controller.dataSource.length + 1));
  }

}

class PageSizeGridView<T> extends GetView<PageSizeLogic<T>>{
  @override
  final  PageSizeLogic<T> controller;
  PageSizeGridView({super.key, required this.itemBuilder,required this.controller,this.shrinkWrap = true,this.itemCount,required this.gridDelegate,this.physics,this.padding,this.emptyHeight});
  final ItemWidgetBuilder<T> itemBuilder;
  final bool shrinkWrap;
  ///用于测试 不建议写
  final int? itemCount;
  final SliverGridDelegate gridDelegate;
  ScrollPhysics? physics;
  final EdgeInsetsGeometry? padding;
  final double? emptyHeight;

  @override
  Widget build(BuildContext context) {
    return
      AppRefresh(
          onRefresh: () {
            controller.onRefresh();
          },
          child:
          controller.dataSource.isEmpty
              ?  AppEmptyView().addContainer(height: this.emptyHeight ?? 500.h,color: Colors.transparent):
    GridView.builder(
    shrinkWrap: shrinkWrap,
    physics: physics,
    padding: padding,
    gridDelegate: gridDelegate,
    itemBuilder: (context,index){
      if (index == controller.dataSource.length && controller.autoPage == true) {
        controller.onLoadMore();
        return Visibility(visible: !controller.noMore, child: const CupertinoActivityIndicator());
      }
      return itemBuilder(context, index, controller.dataSource[index]);
      },itemCount:  controller.noMore ? (itemCount ?? controller.dataSource.length) : (controller.dataSource.length + 1)
      )
    );

          // ListView.builder(padding: EdgeInsets.zero,itemBuilder: (context, index) {
          //   if (index == controller.dataSource.length) {
          //     controller.onLoadMore();
          //     return Visibility(visible: !controller.noMore, child: const CupertinoActivityIndicator());
          //   }
          //   return itemBuilder(context, index, controller.dataSource[index]);
          // }, itemCount: controller.noMore ? (itemCount ?? controller.dataSource.length) : controller.dataSource.length + 1));
  }

}

class ListParameter {
  int pageNum = 0;
  int pageSize = 10;
  ///true 不分页  false分页
  // bool pageSizeZero = false;

  static ListParameter defaultArg() {
    return ListParameter.fromJson({
      "pageNum": 1,
      "pageSize": 10,
    });
  }

  ListParameter({
    required this.pageNum,
    required this.pageSize,
    // required this.pageSizeZero,
  });

  ListParameter.fromJson(Map<String, dynamic> json) {
    pageNum = json['pageNum'];
    pageSize = json['pageSize'];
    // pageSizeZero = json['pageSizeZero'];
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = <String, dynamic>{};
    data['pageNum'] = pageNum;
    data['pageSize'] = pageSize;
    // data['pageSizeZero'] = pageSizeZero;
    return data;
  }
}

class PageSizeData<T> {
  List<T>? list;
  int? pageNum;
  int? pageSize;
  int? pages;
  int? total;

  PageSizeData(
      {this.list, this.pageNum, this.pageSize, this.pages, this.total});

  static PageSizeData<T> fromJson<T>(Map<String, dynamic> json,T Function(Map<String,dynamic>) fromJsonT,) {
    var _data = json["list"] as List?;
    var list = _data?.map((e) =>  fromJsonT(e)).toList();
    return PageSizeData<T>(
      pageNum: json['pageNum'],
      pageSize: json['pageSize'] ?? '',
      pages: json['pages'],
      total:json['total'],
      list:list,
    );
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = <String, dynamic>{};
    if (list != null) {
      ///todo list没转成json
    }
    data['pageNum'] = pageNum;
    data['pageSize'] = pageSize;
    data['pages'] = pages;
    data['total'] = total;
    return data;
  }
}